/**
 * 摘要：
 *    Clipboard API 定义了访问系统剪贴板的 API，提供了覆盖默认剪贴行为操作，并且可以直接访问剪贴板信息。
 * Clipboard API 构建于 Promessing API 规则之下，操作需要用户授权。
 * Clipboard API 被设计计划用来取代现行的 document.execCommand() 方法。
 * Clipborad API 由两个部分构成：
 *    1：Async Clipboard API，对应 navigator.clipboard 对象；
 *        提供直接访问剪贴板的方法，支持读写剪贴板数据，因此被选为“强力特性”，要求受控于 Permission API。
 *    2：ClipboardEvent API ，剪贴板事件组；
 *        提供方法和钩子操作剪切、赋值、粘贴的基本行为，在必要时改变剪贴板的内容。
 * 
 * 兼容性：
 *    数据来自 MDN 文档，对于 Async Clipboard API，Chrome 和 Firefox 均提供基本支持，但分别要求版本在 66 和 63 以上。目前来看兼容性差
 *    对于 ClipboardEvent API 兼容性优秀，可放心使用（除了 ClipboardEvent() 构造函数在 Edge 和 safari 上不一定）
 */

let oTa = document.getElementById('text');
// clipboardEvent 一大特点是：关注点在于游标位置是否在可编辑上下文中，用于区分是否需要操作页面视图完成剪切、赋值、粘贴的可见行为。
/**
 * 当游标处于可编辑上下文时，不论是右键菜单还是快捷键都会触发，
 * 当游标在非可编辑上下文中时，右键菜单的“复制”行为不会触发（至少 chrome 中）
 * 当使用 富文本编辑 API 时，也能触发。
 * 下面三个事件的事件对象中，均有一个 DataTransfer 类型的 clipboardData 字段，可以使用标准的 DataTransfer 方法访问剪贴板。
 * 但有一个限制，就是 clipboard API 只能在 ClipboardEvent 处理函数中访问剪贴板
 * 
 * MDN document of DataTransfer:
 *  https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer
 */

// 重写默认的复制行为
document.addEventListener('copy', (e) => {
  console.log(e.clipboardData);
  // 先是否存在选中内容，若存在再开始下面的逻辑
  // e.clipboardData 初始为空，但我们可以设置成想要的数据
  e.clipboardData.setData('text/plain', 'Hello Clipboard this is copy'); // 会把 text/plain 类型的数据设置给剪贴板
  e.clipboardData.setData('text/html', '<b>Hello Clipboard this is copy</b>'); // 忽略

  e.preventDefault(); // 阻止默认行为，是必要的，否则会使用当前文档中被选中的内容设置剪贴板
});
// 重写默认的剪切行为
document.addEventListener('cut', (e) => {
  console.log(e.clipboardData);
  // 先是否存在选中内容，且是否处于可编辑的上下文中，若均满足再开始下面的逻辑
  // e.clipboardData 初始为空，但我们可以设置成想要的数据
  e.clipboardData.setData('text/plain', 'Hello Clipboard this is cut');

  // 因为会取消 cut 操作，所以需要手动的删除当前选择的文本
  oTa.value = '';

  e.preventDefault();
});
// 重写粘贴的默认行为
document.addEventListener('paste', (e) => {
  console.log(e.clipboardData);
  // 粘贴行为中不同的是，store mode 是 read-only 的，因此 setData() 不能改变数据，而是新增插入一条数据，也不会改变剪贴板
  // e.clipboardData 包含要粘贴的数据
  let oldData = e.clipboardData.getData('text/plain');
  let newData = '<b>Ha Ha!</b>' + oldData;

  // 因为组织了粘贴的默认事件，因此需要自己实现粘贴，往往涉及到 selection API
  // 这里简化操作
  oTa.value = newData;

  e.preventDefault();
});

let oBtn = document.getElementById('copy');
oBtn.addEventListener('click', () => {
  document.execCommand('copy', false, oTa.value);
});

/**
 * Async CLipboard API 
 *  挂载在 navigator.clipboard 对象上
 */
// read(): 方法
let oBtnRead = document.getElementById('asyncRead');
oBtnRead.addEventListener('click', () => {
  // 当 readText 执行后会弹出一个 prompt 提示用户脚步想要查看复制到剪贴板的文字和图片
  // 此时如果拒绝，可以在返回的额 Promise 中 catch 到一个 undefined。
  // 
  navigator.clipboard.readText().then((res) => {
    console.log(res); // 编辑时间，2019.3.4，当前 chrome 版本 72，不支持获取图片的拷贝内容。
  }).catch((e) => {
    console.error(e);
  })
})
let oInput = document.getElementById('asyncWrite');
let oBtnWrite = document.getElementById('asyncBtnWrithe');
oBtnWrite.addEventListener('click', () => {
  navigator.clipboard.writeText(oInput.value).then((res) => {
    console.log('copy success');
  }).catch(e => {
    console.error(e);
  })
})

/**
 * 后记：在当前版本的 Chrome 中（72），navigator.clipboard 对象只实现了，readText 和 writeText 两个方法
 * 规范实现远远不够完善，且 Async Clipboard API 的兼容性也远远不足，暂时只能作为知识被了解
 */